using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;
using Volo.Abp.AspNetCore.Mvc;
using TenantManagementService.Monitoring;

namespace TenantManagementService.Controllers
{
    /// <summary>
    /// 健康检查控制器
    /// </summary>
    [ApiController]
    [Route("health")]
    [IgnoreAntiforgeryToken] // 健康检查端点不需要 CSRF 保护
    public class HealthController : AbpControllerBase
    {
        private readonly HealthCheckService _healthCheckService;
        private readonly ILogger<HealthController> _logger;

        public HealthController(
            HealthCheckService healthCheckService,
            ILogger<HealthController> logger)
        {
            _healthCheckService = healthCheckService;
            _logger = logger;
        }

        /// <summary>
        /// 简单健康检查（用于负载均衡器等）
        /// </summary>
        [HttpGet("")]
        public async Task<IActionResult> GetSimpleHealthAsync()
        {
            try
            {
                var healthSummary = await _healthCheckService.GetHealthSummaryAsync();

                var statusCode = healthSummary.OverallStatus switch
                {
                    HealthStatus.Healthy => StatusCodes.Status200OK,
                    HealthStatus.Warning => StatusCodes.Status200OK, // 警告状态也返回200，但内容包含警告信息
                    HealthStatus.Unhealthy => StatusCodes.Status503ServiceUnavailable,
                    _ => StatusCodes.Status503ServiceUnavailable
                };

                return statusCode == StatusCodes.Status200OK ?
                    Ok(new
                    {
                        status = "healthy",
                        message = "租户管理服务运行正常",
                        timestamp = DateTime.UtcNow,
                        uptime_seconds = healthSummary.UptimeSeconds
                    }) :
                    StatusCode(statusCode, new
                    {
                        status = "unhealthy",
                        message = "租户管理服务运行异常",
                        timestamp = DateTime.UtcNow,
                        issue_count = healthSummary.IssueCount
                    });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "简单健康检查失败");
                return StatusCode(StatusCodes.Status503ServiceUnavailable, new
                {
                    status = "unhealthy",
                    message = "健康检查异常",
                    timestamp = DateTime.UtcNow,
                    error = ex.Message
                });
            }
        }

        /// <summary>
        /// 详细健康检查
        /// </summary>
        [HttpGet("detailed")]
        public async Task<IActionResult> GetDetailedHealthAsync(CancellationToken cancellationToken = default)
        {
            try
            {
                var healthStatus = await _healthCheckService.PerformComprehensiveHealthCheckAsync(cancellationToken);

                var statusCode = healthStatus.OverallStatus switch
                {
                    HealthStatus.Healthy => StatusCodes.Status200OK,
                    HealthStatus.Warning => StatusCodes.Status200OK,
                    HealthStatus.Unhealthy => StatusCodes.Status503ServiceUnavailable,
                    _ => StatusCodes.Status503ServiceUnavailable
                };

                var response = new
                {
                    status = GetStatusText(healthStatus.OverallStatus),
                    overall_status = healthStatus.OverallStatus.ToString(),
                    timestamp = healthStatus.LastCheckTime,
                    components = healthStatus.ComponentStatus,
                    metrics = healthStatus.Metrics,
                    issues = healthStatus.Issues,
                    issue_count = healthStatus.Issues.Count
                };

                return statusCode == StatusCodes.Status200OK ?
                    Ok(response) :
                    StatusCode(statusCode, response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "详细健康检查失败");
                return StatusCode(StatusCodes.Status503ServiceUnavailable, new
                {
                    status = "unhealthy",
                    overall_status = "Unhealthy",
                    timestamp = DateTime.UtcNow,
                    components = new Dictionary<string, string>(),
                    metrics = new Dictionary<string, object>(),
                    issues = new[] { $"健康检查异常: {ex.Message}" },
                    issue_count = 1
                });
            }
        }

        /// <summary>
        /// 组件健康检查
        /// </summary>
        [HttpGet("components/{componentName}")]
        public async Task<IActionResult> GetComponentHealthAsync(string componentName, CancellationToken cancellationToken = default)
        {
            try
            {
                var healthStatus = await _healthCheckService.PerformComprehensiveHealthCheckAsync(cancellationToken);

                if (!healthStatus.ComponentStatus.ContainsKey(componentName))
                {
                    return NotFound(new
                    {
                        status = "not_found",
                        message = $"组件 '{componentName}' 不存在",
                        available_components = healthStatus.ComponentStatus.Keys
                    });
                }

                var componentStatus = healthStatus.ComponentStatus[componentName];

                var response = new
                {
                    component_name = componentName,
                    status = GetStatusText(componentStatus),
                    status_code = componentStatus.ToString(),
                    timestamp = healthStatus.LastCheckTime,
                    related_metrics = GetRelatedMetrics(healthStatus.Metrics, componentName),
                    related_issues = healthStatus.Issues.Where(issue =>
                        issue.Contains(componentName, StringComparison.OrdinalIgnoreCase)).ToList()
                };

                var statusCode = componentStatus switch
                {
                    HealthStatus.Healthy => StatusCodes.Status200OK,
                    HealthStatus.Warning => StatusCodes.Status200OK,
                    HealthStatus.Unhealthy => StatusCodes.Status503ServiceUnavailable,
                    _ => StatusCodes.Status503ServiceUnavailable
                };

                return statusCode == StatusCodes.Status200OK ?
                    Ok(response) :
                    StatusCode(statusCode, response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "组件健康检查失败: {ComponentName}", componentName);
                return StatusCode(StatusCodes.Status503ServiceUnavailable, new
                {
                    component_name = componentName,
                    status = "unhealthy",
                    status_code = "Unhealthy",
                    timestamp = DateTime.UtcNow,
                    error = ex.Message
                });
            }
        }

        /// <summary>
        /// 健康状态就绪检查（用于 Kubernetes 就绪探针）
        /// </summary>
        [HttpGet("ready")]
        public async Task<IActionResult> GetReadinessAsync(CancellationToken cancellationToken = default)
        {
            try
            {
                var healthStatus = await _healthCheckService.PerformComprehensiveHealthCheckAsync(cancellationToken);

                // 就绪检查要求核心组件必须健康
                var criticalComponents = new[] { "database", "application" };
                var allCriticalHealthy = criticalComponents.All(component =>
                    healthStatus.ComponentStatus.ContainsKey(component) &&
                    healthStatus.ComponentStatus[component] == HealthStatus.Healthy);

                if (allCriticalHealthy)
                {
                    return Ok(new
                    {
                        status = "ready",
                        message = "服务已就绪",
                        timestamp = DateTime.UtcNow,
                        critical_components = criticalComponents.ToDictionary(
                            c => c,
                            c => healthStatus.ComponentStatus.GetValueOrDefault(c, HealthStatus.Unknown).ToString()
                        )
                    });
                }
                else
                {
                    return StatusCode(StatusCodes.Status503ServiceUnavailable, new
                    {
                        status = "not_ready",
                        message = "服务未就绪",
                        timestamp = DateTime.UtcNow,
                        critical_components = criticalComponents.ToDictionary(
                            c => c,
                            c => healthStatus.ComponentStatus.GetValueOrDefault(c, HealthStatus.Unknown).ToString()
                        )
                    });
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "就绪检查失败");
                return StatusCode(StatusCodes.Status503ServiceUnavailable, new
                {
                    status = "not_ready",
                    message = "就绪检查异常",
                    timestamp = DateTime.UtcNow,
                    error = ex.Message
                });
            }
        }

        /// <summary>
        /// 存活检查（用于 Kubernetes 存活探针）
        /// </summary>
        [HttpGet("live")]
        public IActionResult GetLiveness()
        {
            try
            {
                // 存活检查只需要确认进程正在运行
                return Ok(new
                {
                    status = "alive",
                    message = "服务正在运行",
                    timestamp = DateTime.UtcNow,
                    process_id = Environment.ProcessId
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "存活检查失败");
                return StatusCode(StatusCodes.Status503ServiceUnavailable, new
                {
                    status = "not_alive",
                    message = "存活检查异常",
                    timestamp = DateTime.UtcNow,
                    error = ex.Message
                });
            }
        }

        /// <summary>
        /// 获取健康检查统计信息
        /// </summary>
        [HttpGet("statistics")]
        public async Task<IActionResult> GetHealthStatisticsAsync(CancellationToken cancellationToken = default)
        {
            try
            {
                var healthSummary = await _healthCheckService.GetHealthSummaryAsync(cancellationToken);

                return Ok(new
                {
                    success = true,
                    data = healthSummary,
                    timestamp = DateTime.UtcNow
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取健康检查统计信息失败");
                return StatusCode(StatusCodes.Status500InternalServerError, new
                {
                    success = false,
                    message = ex.Message,
                    timestamp = DateTime.UtcNow
                });
            }
        }

        private static string GetStatusText(HealthStatus status)
        {
            return status switch
            {
                HealthStatus.Healthy => "healthy",
                HealthStatus.Warning => "warning",
                HealthStatus.Unhealthy => "unhealthy",
                HealthStatus.Unknown => "unknown",
                _ => "unknown"
            };
        }

        private static Dictionary<string, object> GetRelatedMetrics(Dictionary<string, object> allMetrics, string componentName)
        {
            var relatedMetrics = new Dictionary<string, object>();

            var prefix = componentName + "_";
            foreach (var metric in allMetrics)
            {
                if (metric.Key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
                {
                    relatedMetrics[metric.Key.Substring(prefix.Length)] = metric.Value;
                }
            }

            return relatedMetrics;
        }
    }
}